\documentclass[UTF8]{ctexart}


% \lstset{frame=, basicstyle={\footnotesize\ttfamily}}



% \graphicspath{ {images/} }
\usepackage{ctex}
\usepackage{minted}
\usepackage{graphicx}
\usepackage{pdflscape}
\usepackage{titlesec}
\usepackage{float}
\usepackage[export]{adjustbox}
\usepackage[colorlinks, 
            linkcolor=black,
            anchorcolor=black,
            citecolor=black]{hyperref}

\setcounter{secnumdepth}{4}

\titleformat{\paragraph}
{\normalfont\normalsize\bfseries}{\theparagraph}{1em}{}
\titlespacing*{\paragraph}
{0pt}{3.25ex plus 1ex minus .2ex}{1.5ex plus .2ex}
%-----------------------------------------BEGIN DOC----------------------------------------

\begin{document}
\renewcommand{\contentsname}{目\ 录}
\renewcommand{\appendixname}{附录}
% \renewcommand{\appendixpagename}{附录}
\renewcommand{\refname}{参考文献} 
\renewcommand{\figurename}{图}
\renewcommand{\tablename}{表}
\renewcommand{\today}{\number\year 年 \number\month 月 \number\day 日}

\title{{\Huge U10M11007试点班实验报告{\large\linebreak\\}}{\Large 三级流水线设计报告\linebreak\linebreak}}
%please write your name, Student #, and Class # in Authors, student ID, and class # respectively
\author{\\姓\ 名:王\ 嘉\ 利\\
学\ 号: 2018302278\\
班\ 号: 10011801\\\\
CS 11007 计算机组成与体系结构\\
(春季, 2020)\\\\
西北工业大学\\
计算机学院\\
ERCESI}
\date{\today}
\maketitle
\newpage

%-----------------------------------------ABSTRACT-------------------------------------
\begin{center}
{\Large\bf{摘\ 要\\}}
\end{center}
本次实验在三级流水处理器的基础上设计了五级流水处理器。将指令的执行分为取指、译码、执行、访存、写回五个阶段，
将三级流水线的第三级分为三个阶段。数据通路与三级流水基本一致，增加新的控制通路来处理冒险。
\newpage
%-----------------------------------------ABSTRACT-------------------------------------
\begin{center}
{\Large\bf{版\ 权\ 声\ 明\\}}
\end{center}
该文件受《中华人名共和国著作权法》的保护。ERCESI实验室保留拒绝授权违法复制该文件的权利。任何收存和保管本文件各种版本的单位和个人，未经ERCESI实验室（西北工业大学）同意，不得将本文档转借他人，亦不得随意复制、抄录、拍照或以任何方式传播。 否则，引起有碍著作权之问题，将可能承担法律责任。\newpage
%-----------------------------------------CONTENT-------------------------------------
\begin{center}
\tableofcontents\label{c}
\end{center}
\newpage

%------------------------------------------TEXT--------------------------------------------

%----------------------------------------OVERVIEW-----------------------------------------

\section{概述} \label{overview}%------------------------------
五级流水处理器指令的执行分为取指、译码、执行、访存、写回五个阶段。取指阶段的指令会在译码级提前发送，并完成PC的更新；
译码级，完成指令的译码，在这一级完成分支指令的处理，并提向指令存储器提前发送指令地址；执行级，完成指令运算，并提前发送load指令访问
存储器的地址；访存级，从存储器读出数据，并提交store指令；写回级，将数据写回寄存器，并在这一级处理异常。


%----------------------------------SYSTEM DESIGN------------------------------------------

\begin{landscape}
    
    \begin{figure}[]
        \centering
        % \flushleft    
        \includegraphics[ width=270mm,center]{5-stages-pipeline.png}
        \caption{五级流水处理器结构图}
        \label{fig:singleblock}
    \end{figure}
    \end{landscape}
\newpage
\section{系统设计} \label{sysdes}%------------------------------
\subsection{System Overview}\label{sub:sysover}
五级流水线处理器的结构图如上图所示
\subsection{数据通路}
\begin{itemize}
    \item{\textbf{取指}\   从指令存储器中取出指令，但是指令的地址是在译码时提前发送的。
    而PC可能的取值是PC+4、跳转的地址、异常处理的地址，也有可能来自EPC，因此要用多选器选出PC的值，
    再从InstructionMemory中取出指令。}
    \item{\textbf{译码}\  在这一阶段，需要将执行指令时可能用到的数据准备好，对立即数进行扩展等。
    提前对分支指令的处理，并提前取下一条指令}
    \item{\textbf{执行和写回}\ \  在执行指令时，可以把运算分为移位、算术逻辑运算、比较运算，以及乘除法；
    并且提前处理load指令}
    \item{\textbf{访存}在访存时，
    访存的地址一定是来自ALU的结果，写入的数据是rt的值；}
    \item {\textbf{写回} 对于
    写回，写回寄存器的数据是来自执行和访存的输出，或者是HiLo寄存器等。在译码时产生一信号，对写入的数据进行选择；}
    % \item{\textbf{使用Chisel3描述结构} Chisel是一种强大的结构化硬件描述语言，可以对模块、接口以及操作等进行高效率的描述，与Verilog语言相比较，对电路的结构属性具有更好的封装，对系统的描述更加简化。我们选择Chisel3是因为在Linux系统中，使用Chisel3完全不再依赖工业EDA软件实现电路的逻辑仿真，更有利于学术研究和教学应用。虽然Chisel语法在不同版本差异不大，但是部分修饰符的描述方式仍然具有差别，详细区别请参考: \url{https://github.com/ucb-bar/chisel3/wiki/Chisel3-vs-Chisel2}.}
\end{itemize}
\subsection{控制通路}
控制主要是通过\mintinline{c}{opcode} \ \mintinline{c}{func}解码出来的信号来进行控制的。
每拍将相应的控制信号送到后面的流水线寄存器。
对ALU来讲，控制比较有特点，因为将ALU分成了三个功能不同的ALU，所以
总体上可以直接将\mintinline{c}{opcode}段 \ \mintinline{c}{func}段的后三位来进行控制
关于EPC写入数据的选择信号来出错指令是否在分支延迟槽，如果是则时PC-4,否则时异常指令的PC。

% \textbf{信号列表}
%     \begin{table}[H]
%     \makebox[\linewidth][c]{
%     \begin{tabular}{|c|c|c|c|c|c|c|c|c|c|}
%         \hline
%         & 0           & 1       & 2      & 3    & 4    & 5          & 6   &  7       & 8                         \\ \hline  
%         write\_data\_src & 算术运算ALU  & 比较ALU & 移位ALU & PC+4& HiLo & R[rs] & MEM & CP0      & R[rt] \\ \hline
%     \end{tabular}}
%     \caption{写回数据的选择信号}
% \end{table}

\subsection{冒险}
\subsubsection{数据冒险}
考虑最简单的情况\ref{chart:dHazard},第二条指令,第三个指令以及第四条指令，和第一个指令相关，
and指令需要来自add执行的结果，可以从EX/MEM旁路前递过来；or指令的数据冒险可以通过MEM/WB旁路解决；
对于sub指令和三级流水线一样，认为在它译码的这一拍，add指令先写入到了寄存器，然后再从及寄存器中读出写回的值，即认为
RegFile内部进行了前递。
对于需要多周期完成的MULT/DIV来会在后面考虑。
\begin{table}[H]
    \centering
    \begin{tabular}{|c|c|c|c|c|c|c|c|c|}
        \hline
                                & C1 & C2&C3 &C4 & C5&    &  &  \\ \hline 
    \mintinline{s}{add $1,$2,$3} & F & D & E & M & W &    &  & \\ \hline 
    \mintinline{s}{and $2,$1,$4} &   & F & D & E & M & W  &   & \\ \hline 
    \mintinline{s}{or  $5,$1,$3}  &  &    & F & D &E & M  & W  & \\ \hline 
    \mintinline{s}{sub $3,$1,$2} &   &   &   & F & D & E  & M & W \\ \hline
    \end{tabular}
    \caption{data hazard}\label{chart:dHazard}
\end{table}

再来考虑累加时可能出现的冒险,第三条指令的需要的数据是来自第二条的结果，此时EX/MEM和MEM/WB旁路
都时存在的，但是因该选择EX/MEM旁路而不是MEM/WB旁路

\begin{table}[h]
    \centering
    \begin{tabular}{|c|c|c|c|c|c|c|c|}
        \hline
                                     & C1 & C2 & C3 & C4 & C5 & C6 & C7 \\\hline
        \mintinline{s}{add $1,$2,$3} & F  & D  & E  & M  & W  &    &    \\\hline
        \mintinline{s}{add $1,$1,$2} &    & F  & D  & E  & M  & W  &    \\\hline
        \mintinline{s}{add $1,$1,$2} &    &    & F  &  D & E  & M  & W  \\\hline
    \end{tabular}
\end{table}
     
同样分析时序关系，当出现lw指令的相关时，需要停顿一拍

\subsubsection{控制冒险} 

当出现分支指令时，可能会出现控制冒险。通过分支延迟槽和提前处理分支指令来处理控制冒险。当一条分支指令进入取指级
时；下一拍会分支延迟槽处的指令进入取指，分支指令进入译码级，计算出分支指令的跳转地址，当一下时钟上升沿到来时，就能
跳转到跳转的目标

\subsubsection{异常处理}

当出现异常时，流水线记录异常信号，在最后一级提交异常并将流水线清空，并且提前将异常处理的地址发送给指令存储器
。流水线清空通过一个控制单元完成。


% -----------------------------------BLOCKS DESIGN----------------------------------------
\section{模块详细设计}
\subsection{数据通路相关}
\subsubsection{ImmExt 扩展单元} 
\paragraph{功能描述} 
对16bits立即数进行扩展
\paragraph{接口定义}
\begin{table}[H]
    \centering
    \begin{tabular}{|c|c|c|c|}
        \hline  
        名称 & 位宽 & 方向 & 描述 \\ \hline 
        imm  & 16 & in & 立即数\\ \hline 
        extImm & 32 & out & 扩展后的立即数 \\ \hline
        extOp & 1 & in & 符号还是无符号扩展\\ \hline
    \end{tabular}
    \caption{ImmExt 接口}
\end{table}

\paragraph{逻辑控制}
可以发现，只有逻辑运算时才进行无符号扩展，进一步可以用\mintinline{c}{opcode[3]&opcode[2]}作为extOp
\begin{table}[H]
    \centering
    \begin{tabular}{|c|c|c|}
        \hline
        extOp & 0 & 1 \\ \hline
        扩展  & signed & unsigned \\ \hline
    \end{tabular}
\end{table} 
\subsubsection{branchPC }
用来计算跳转的地址。
\begin{table}[H]
    \centering
    \begin{tabular}{|c|c|c|c|}
        \hline  
        名称 & 位宽 & 方向 & 描述 \\ \hline 
        extImm & 32 & in & 扩展后的立即数 \\ \hline
        PC & 32 & in & pc \\ \hline 
        target & 32 & in & J，JR等指令的跳转目标 \\ \hline 
        branchOp & 1 & in & 控制信号 \\ \hline
        branchPC & 32 & out & 跳转目标\\ \hline
    \end{tabular}
\end{table}
branchOp控制跳转地址的计算，通过\mintinline{c}{opcode[2:0]}产生这个信号。如果
\mintinline{c}{opcode[2:0]}是0，2，3输出是target，否则是extImm与PC相加的结果。
\subsubsection{isBranch}
用来产生next PC的选择信号
\begin{table}[H]
    \centering
    \begin{tabular}{|c|c|c|c|}
        \hline  
        名称 & 位宽 & 方向 & 描述 \\ \hline 
        valA & 32 & in & R[rs] \\ \hline
        valB & 32 & in & R[rt] \\ \hline 
        rt & 5 & in & branch指令的rt段 \\ \hline 
        opcode & 6 & in & 控制信号 \\ \hline
        PCSel & 2 & out & nextPC的选择信号\\ \hline
    \end{tabular}
\end{table}
\subsubsection{Reg File}
\paragraph{功能描述}
32个通用寄存器堆，实现寄存器的读写
\paragraph{接口定义} 见表\ref{rf}
\begin{table}[H]
    \centering
    \begin{tabular}{|c|c|c|c|}
        \hline  
        名称 & 位宽 & 方向 & 描述 \\
        \hline  
        clk & 1 & in & clock \\ \hline
        rst\_n & 1 & in  & reset \\ \hline
        readReg1 & 5 & in &  读寄存器1 \\ \hline
        readReg2 & 5 & in & 读寄存器2 \\ \hline
        write\_data & 32 & in & 写数据 \\ \hline
        writeReg & 5 & in & 写寄存器 \\ \hline
        write\_en & 1 & in & 写使能 \\ \hline
        read\_data1 & 32 & out & 读数据 \\ \hline 
        read\_data2 & 32 & out & 读数据 \\ \hline

    \end{tabular}
    \caption{RF接口}
    \label{rf}
\end{table}
\paragraph{逻辑控制}
因为受到冒险和异常的影响，需要能够清空流水线，所以write\_en的控制会较其他信号复杂一些
当发现有控制冒险，或者在在执行指令时发现异常，应该让相应指令的write\_en置零。当出现
控制冒险时，控制冒险单元输出的flush信号为1，通过flush让write\_en和0取选择。 

但出现数据冒险的时候，此时RF的写使能为1，且同时
\begin{minted}{c}
    readReg1 == writeReg or readReg2 == writeReg
\end{minted}
RF进行内部forward，读出的数据选择\mintinline{c}{write_data}。
\subsubsection{ALU}\label{sub:alu}
\paragraph{功能描述}
\begin{itemize}
    \item \textbf{算术、逻辑运算ALU}\  用来进行算术运算与逻辑运算，处理类似\mintinline{c}{ADD AND}这类指令
    \item \textbf{移位运算ALU}\  用来进行移位运算， 处理类似于\mintinline{c}{SLL SRL} 这类指令 
    \item \textbf{比较运算ALU} \ 用来进行比较, 处理类似于\mintinline{c}{SLT}这类指令
\end{itemize}
\paragraph{接口定义}
\textbf{算术、逻辑运算ALU}
\begin{table}[H]
    \centering
    \begin{tabular}{|c|c|c|c|}
        \hline  
        名称 & 位宽 & 方向 & 描述 \\
        \hline  
        alu\_A & 32 & in & ALU的操作数 \\
        \hline 
        alu\_B & 32 & in & ALU的操作数 \\
        \hline 
        aluOp & 3 & in & ALU控制信号 \\
        \hline
        alu\_out & 32 & out & ALU计算输出 \\
        \hline
        overflow & 1 & out & 整数溢出标志 \\
        \hline
    \end{tabular}
    \caption{ALU接口}
\end{table}

\textbf{移位运算ALU 比较运算ALU}
剩下两个ALU模块的接口是一样的
\begin{table}[H]
    \centering
    \begin{tabular}{|c|c|c|c|}
        \hline  
        名称 & 位宽 & 方向 & 描述 \\
        \hline  
        alu\_A & 32 & in & ALU的操作数 \\
        \hline 
        alu\_B & 32 & in & ALU的操作数 \\
        \hline 
        aluOp & 3 & in & ALU控制信号 \\
        \hline
        alu\_out & 32 & out & ALU计算输出 \\
        \hline

    \end{tabular}
    \caption{ALU接口}
\end{table}

\paragraph{逻辑控制} 
\textbf{算术、逻辑运算ALU} \\
\begin{table}[H]
    \centering
    \begin{tabular}{|c|c|c|c|c|c|c|c|c|}
        \hline
        aluOp & 000 & 001 & 010 & 011 & 100 & 101 & 110 & 111 \\ \hline
        运算  & ADD & ADDU & SUB & SUBU & AND & OR & NOR & XOR \\ \hline
    \end{tabular}
    \caption{ALU控制}
\end{table} 

ALU的两个操作数一个是来自rs，一个来自rt或者立即数。用\mintinline{c}{opcode[5:3]}来选择
\begin{minted}{c}
    if opcode[5:3] == 000 :
        alu_B = R[rt]
    else :
        alu_B = extImm 
\end{minted}

\textbf{移位运算ALU} \\
\begin{table}[H]
    \centering
    \begin{tabular}{|c|c|c|c|c|c|c|c|c|}
        \hline
        aluOp & 000 & 001 & 010 & 011 & 100 & 101 & 110 & 111 \\ \hline
        运算  & SLL & xxx & SRL & SRA & SLLV & xxx & SRLV & SRAV \\ \hline
    \end{tabular}
        \caption{ALU控制(xxx是不关心的情况)}
\end{table}
这些移位指令都是R-type指令，ALU的操作数alu\_B来自rt，alu\_A来自R[rs]或者sa
\begin{minted}{c}
    alu_A = func[3] ? R[rt] : sa
\end{minted}

\textbf{比较运算ALU} \\
\begin{table}[H]
    \centering
    \begin{tabular}{|c|c|c|c|}
        \hline
        aluOp & 010 & 011 & other\\ \hline
        运算  & signed cmp & unsigned cmp  & xxx \\ \hline
    \end{tabular}
        \caption{ALU控制(xxx是不关心的情况)}
\end{table}
ALU的操作数和算术逻辑ALU的操作数一致

\subsubsection{MULT DIV}
乘除法通过移位的方法实现，完成一次乘法或者除法需要32拍。如果考虑不让乘除阻塞流水线，
除非出现数据冒险，但这样可能使频率降低，而且乘法和除法的指令数可能并不是很多。所以，当遇到乘法和除法的时候就让流水线停下来。
用状态机控制乘除法单元，如果乘除法运算正在进行，就阻塞流水线，在计算结束之后将数据送到流水线，最后写回Hi\ Lo寄存器

\begin{table}[H]
    \centering
    \begin{tabular}{|c|c|c|c|}
        \hline  
        名称 & 位宽 & 方向 & 描述 \\ \hline
        valA & 32 & in & 操作数1 \\ \hline
        valB & 32 & in & 操作数2 \\\hline
        mult\_div\_op & 2 & in & 控制信号 \\ \hline
        en & 1 & in & 使能 \\ \hline
        valHi & 32 & out & Hi的输出\\\hline
        valLo & 32 & out & Lo的输出\\\hline
        % write\_HiLo & 1 & out & 写HiLo寄存器使能 \\ \hline
        running & 1 & out & is run \\ \hline
        state & 5 & out & 状态 \\ \hline
    \end{tabular}
\end{table}

在开始的第一拍，将输入数据写入到单元内部的寄存器，开始计算，而且在计算完成之前，内部得寄存器都不能被写入外部
的输入数据。在输出结果时如果先将结果写回到内部的寄存器，再送到流水线寄存器，
这样会空掉一拍，因此在计算结束后，让输出送到流水线寄存器和写回到内部的寄存器同时进行。

将MULT/DIV模块作为一个单独的模块，进行乘除时，数据在译码之后，下一拍直接写入到模块的内存寄存器，开始计算

\subsubsection{CP0}
关于CP0寄存器的模块
\begin{table}[h]
    \centering
    \begin{tabular}{|c|c|c|c|}
        \hline
        名称 & 位宽 & 方向 & 描述 \\ \hline
        write\_cp0\_reg & 1 & in & 写使能 \\\hline
        cp0\_write\_data & 32 & in & 写数据 \\\hline
        rd  & 5 & in & 索引 \\\hline
        sel & 3 & in & 索引 \\\hline
        cp0\_read\_data & 32 & out & cp0读数据  \\\hline
    \end{tabular}
\end{table}

\subsection{控制通路相关}

\subsubsection{MEM Interface}

\paragraph{IM Interface}
和inst\_sram进行交互，处理指令提前发送
\begin{table}[h]
    \centering
    \begin{tabular}{|c|c|c|c|}
        \hline
        名称 & 位宽 & 方向 & 描述 \\ \hline
        PCSrc & 1  & in & 取指地址的选择 \\\hline
        PC4 & 32   & in & PC+4 \\\hline
        nextPC & 32 & in & 跳转目标\\\hline
        exception & 1 & in &例外信号 \\\hline
        inst\_in & 32 & in & 从IM读出的指令 \\\hline
        inst\_sram\_en & 1 & out & 指令存储使能 \\\hline
        inst\_sram\_wen & 4 & out & 指令存储器写使能 \\\hline
        inst\_sram\_addr & 32 & out & 读IM地址 \\\hline
        inst\_out & 32 & out & 指令 \\\hline
    \end{tabular}
\end{table}

\paragraph{DM Interface}
和data\_sram交互，处理load指令提前发送
\begin{table}[h]
    \centering
    \begin{tabular}{|c|c|c|c|}
        \hline
        名称 & 位宽 & 方向 & 描述 \\ \hline
        EX\_addr & 32 & in & EX发送的地址 \\\hline
        MEM\_addr & 32 & in & MEM发送的地址 \\\hline
        EX\_Inst & 32 & in & EX级的指令 \\\hline
        MEM\_Inst & 32 & in & MEM级指令 \\\hline
        data\_sram\_rdata\_in & 32 & in & 从DM读出的值 \\\hline
        data\_sram\_en & 1 & out & DM使能 \\\hline
        data\_sram\_wen & 4 & out & DM写使能 \\\hline
        data\_sram\_wdata & 32 & out &DM写数据 \\\hline
        data\_sram\_rdata\_out & 32 & out & 从DM读出的值 \\\hline
    \end{tabular}
\end{table}

\subsubsection{Control}
控制单元，控制流水线的停顿和清空
\begin{table}[h]
    \centering
    \begin{tabular}{|c|c|c|c|}
        \hline
        名称 & 位宽 & 方向 & 描述 \\ \hline
        exception & 1 & in & 是否有异常 \\\hline
        mult\_div\_run & 1 & in & 乘除法停顿 \\\hline
        ID\_Inst & 32 & in & ID级指令 \\\hline
        EX\_Inst & 32 & in & EX级指令 \\\hline 
        IF\_stall & 1 & out & IF停顿 \\\hline
        ID\_stall & 1 & out & ID停顿\\\hline
        IF\_flush & 1& out & IF清空\\\hline
        ID\_flush & 1 & out & ID清空\\\hline
        EX\_flush & 1 & out & EX清空 \\\hline
        MEM\_flush & 1 & out & MEM清空 \\\hline
        WB\_flush & 1 & out & WB清空 \\\hline
    \end{tabular}
\end{table}
当出现乘除法时，因为用32个周期完成，因此需要停顿流水线；当出现异常时清空流水线；通过判断译码级和执行级的指令判断是否因为
load指令相关需要停顿。

\subsubsection{Exception}
对异常进行探测和处理
\begin{table}[H]
    \centering
    \begin{tabular}{|c|c|c|c|}
        \hline  
        名称 & 位宽 & 方向 & 描述 \\ \hline
        trap & 1 & in & 自陷指令异常标志 \\ \hline
        overflow & 1 & in & 整数溢出异常标志 \\ \hline 
        DM\_read\_addrFault & 1 & in & 读地址错异常标志 \\ \hline     
        DM\_write\_addrFault & 1 & in & 写地址错异常 \\\hline
        IF\_addrFault & 1 & in & 取指地址错 \\\hline 
        ri\_fault & 1 & in & 保留指令\\\hline
        soft\_int & 1 & in & 软件中断异常 \\\hline
        cause & 32 & out & 写到Cause寄存器的原因 \\ \hline 
        write\_cause\_en & 1 & out & 写cause的使能 \\ \hline
        exception & 1 & out & 异常标志 \\ \hline
    \end{tabular}
    
\end{table}
addrFault信号来自判读是否地址错单元的输出。exception信号来自各个异常的或。exception信号需要发给控制单元和IM Interface。



%add more subsections for other block in you CPU design.
\subsection{流水级顶层module}
\subsubsection{IF}
\begin{table}[H]
    \centering
    \begin{tabular}{|c|c|c|c|}
        \hline  
        名称 & 位宽 & 方向 & 描述 \\ \hline
        clk & 1 & in & clock\\ \hline
        rst\_n  & 1  & in & reset \\ \hline
        nextPC & 32 & in & 计算出的nextPC \\ \hline
        PCSRc & 2 & in & PC选择信号 \\ \hline
        flush & 1 & in & 清空信号 \\ \hline 
        stall\_pc & 1 & in & 暂停标志\\\hline
        fetch\_addr\_fault & 1  & out & 取指地址错 \\\hline 
        % IM\_en & 1 & in & instMem 使能 \\ \hline
        PC & 32 & out & PC值  \\ \hline
        PC4 & 32 & out & PC+4 \\ \hline 
        Inst & 32 & out & 指令 \\ \hline 
    \end{tabular}
    \caption{IF接口}
\end{table}
\subsubsection{ID}
因为考虑后面的流水级可能要使用关于Inst的信息，所以直接将Inst传到流水线寄存器。而且对于
一些信号是要从第三级流水拉回来，同名的信号也会在译码产生，用in和out后缀来区分。
\begin{table}[H]
    \centering
    \begin{tabular}{|c|c|c|c|}
        \hline  
        名称 & 位宽 & 方向 & 描述 \\ \hline
        clk & 1 & in & clock\\ \hline
        rst\_n  & 1  & in & reset \\ \hline
        Inst & 32 & in & 指令 \\ \hline
        PC4\_in(out) & 32 & in(out) & PC+4 \\ \hline
        PC\_in(out) & 32 & in(out) & PC  \\ \hline
        write\_dst\_in(out) & 5 & in(out) & 寄存器目标 \\ \hline
        write\_reg\_in(out) & 1 & in(out) & RF写使能 \\ \hline
        write\_reg\_data & 32 & in & 写会寄存器的值 \\ \hline 
        write\_epc & 1 &in & 写EPC使能 \\ \hline 
        write\_cp0reg\_in(out) & 1 & in(out) & 写CP0寄存器使能  \\ \hline
        fetch\_addr\_fault\_in(out) & 1 & in(out) & 取指地址错 \\\hline
        ri\_fault & 1 & out & 保留指令 \\\hline
        flush & 1 & in & 清空信号 \\ \hline 
        reg\_data1 & 32 & out & 寄存器读数据 \\ \hline 
        reg\_data2 & 32 & out & 寄存器读数据 \\ \hline
        extImm & 32 & out & 扩展后的立即数 \\ \hline
        % write_dst_out & 5 & out & 译码得到的写寄存器目标 \\ \hline
        nextPC & 32 & out & 下一个PC \\ \hline
        Inst & 32 & out & 指令 \\ \hline
        write\_hilo & 1 & out & HI LO写使能 \\ \hline
        mult\_div\_en & 1 &out & MULT/DIV模块使能 \\ \hline
        data\_sram\_wen & 4 & out & 写DMem使能 \\ \hline
        trap & 1 & out & 是否出现自陷指令 \\ \hline 
        extOp & 2 & out & MEM读出数据后的扩展控制信号 \\ \hline
        write\_data\_src & 3 & out & 写回数据的选择信号 \\ \hline
    \end{tabular}
    \caption{ID接口}
\end{table}

必要的控制信号也要输出
\subsubsection{EX}
EX的输入基本都来自于ID级译码的结果
\begin{table}[H]
    \centering
    \begin{tabular}{|c|c|c|c|}
        \hline  
        名称 & 位宽 & 方向 & 描述 \\ \hline
        clk & 1 & in & clock\\ \hline
        rst\_n  & 1  & in & reset \\ \hline
        Inst & 32 & in & 指令 \\ \hline
        PC4\_in(out) & 32 & in(out) & PC+4 \\ \hline
        PC\_in(out) & 32 & in(out) & PC  \\ \hline
        reg\_data1 & 32 & in & 寄存器读数据 \\ \hline 
        reg\_data2 & 32 & in & 寄存器读数据 \\ \hline
        write\_hilo & 1 & in & HI LO写使能 \\ \hline
        % write\_mem & 4 & in & 写DMem使能 \\ \hline
        data\_sram\_wen & 4 & in & DMem使能 \\ \hline
        trap & 1 & in & 是否出现自陷指令 \\ \hline 
        extOp & 2 & in & MEM读出数据后的扩展控制信号 \\ \hline 
        write\_data\_src & 3 & in & 写回数据选择信号 \\ \hline
        ri\_fault\_in(out) & 1 & in & 保留指令 \\\hline
        fetch\_addr\_fault\_in(out) & 1 & in(out) & 取指地址错 \\\hline
        alu\_a\_out & 32 & out & ALU\_a输出 \\\hline
        alu\_c\_out & 32 & out & ALU\_c输出 \\\hline
        alu\_s\_out & 32 & out & ALU\_s输出 \\\hline
        % write\_reg\_data & 32 & out & 写回寄存器的值 \\ \hline 
        % exception & 1  &out & 是否有例外 \\ \hline
        data\_sram\_addr & 32 & out & 访存地址的地址 \\\hline
        overflow & 1 & 是否出现溢出例外 \\\hline
    \end{tabular}
    \caption{EX接口}
\end{table}

\subsubsection{MEM}

这一级和DM\_interface交互

\begin{table}[H]
    \centering
    \begin{tabular}{|c|c|c|c|}
        \hline  
        名称 & 位宽 & 方向 & 描述 \\ \hline
        clk & 1 & in & clock\\ \hline
        rst\_n  & 1  & in & reset \\ \hline
        Inst & 32 & in & 指令 \\ \hline
        PC4\_in(out) & 32 & in(out) & PC+4 \\ \hline
        PC\_in(out) & 32 & in(out) & PC  \\ \hline
        reg\_data1 & 32 & in & 寄存器读数据 \\ \hline 
        reg\_data2 & 32 & in & 寄存器读数据 \\ \hline
        write\_hilo & 1 & in & HI LO写使能 \\ \hline
        data\_sram\_wen\_in(out) & 4 & in & 写DMem使能 \\ \hline
        data\_sram\_rdata & 32 & in & data\_sram读出的数据 \\\hline
        % data\_sram_wen & 4 & in & DMem使能 \\ \hline
        extOp & 2 & in & MEM读出数据后的扩展控制信号 \\ \hline 
        trap\_in(out) & 1 & in & 是否出现自陷指令 \\ \hline 
        overflow\_in(out) & 1 & 是否出现溢出例外 \\\hline
        ri\_fault\_in(out) & 1 & in & 保留指令 \\\hline
        fetch\_addr\_fault\_in(out) & 1 & in(out) & 取指地址错 \\\hline
        addr\_fault & 1 & out & 地址错例外 \\\hline
        write\_data\_src & 3 & in & 写回数据选择信号 \\ \hline
        write\_reg\_data & 32 & out & 写回寄存器的值 \\ \hline 
        % exception & 1  &out & 是否有例外 \\ \hline
        addr\_fault & 1 & out & 地址错例外 \\\hline
    \end{tabular}
    \caption{MEM接口}
\end{table}


\subsubsection{WB}

\begin{table}[H]
    \centering
    \begin{tabular}{|c|c|c|c|}
        \hline  
        名称 & 位宽 & 方向 & 描述 \\ \hline
        clk & 1 & in & clock\\ \hline
        rst\_n  & 1  & in & reset \\ \hline
        Inst & 32 & in & 指令 \\ \hline
        PC4\_in(out) & 32 & in(out) & PC+4 \\ \hline
        PC\_in(out) & 32 & in(out) & PC  \\ \hline
        reg\_data1 & 32 & in & 寄存器读数据 \\ \hline 
        reg\_data2 & 32 & in & 寄存器读数据 \\ \hline
        write\_hilo & 1 & in & HI LO写使能 \\ \hline
        trap & 1 & in & 是否出现自陷指令 \\ \hline 
        overflow & 1 & in & 是否出现溢出例外 \\\hline
        ri\_fault\_in(out) & 1 & in & 保留指令 \\\hline
        fetch\_addr\_fault\_in(out) & 1 & in(out) & 取指地址错 \\\hline
        addr\_fault & 1 & out & 地址错例外 \\\hline
        extOp & 2 & in & MEM读出数据后的扩展控制信号 \\ \hline 
        write\_data\_src & 3 & in & 写回数据选择信号 \\ \hline
        write\_reg\_data & 32 & out & 写回寄存器的值 \\ \hline 
        exception & 1  &out & 是否有例外 \\ \hline
    \end{tabular}
    \caption{WB接口}
\end{table}

\subsection{流水线寄存器}
流水线寄存器的主要输入输出来自上一级的输出和下一级的输入。输入还有clk，rst\_n,
以及暂停流水线的stall信号
% -----------------------------------Appendix----------------------------------------
\appendix
% \section{代码}\label{sub:app.code}
% 请在附录\ref{sub:app.code}中添加代码。请使用如下Scala的语法高亮描述方法。

\newpage
% -----------------------------------REFERENCE----------------------------------------
\begin{thebibliography}{9}
    MK.Computer.Organization.and.Design.5th.Edition
\end{thebibliography}
\end{document}

